import pandas as pd
import matplotlib.pyplot as plt
# 使用非交互式后端，确保程序可以自动运行完成
plt.switch_backend('Agg')
import seaborn as sns
import mplfinance as mpf
from datetime import datetime

# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei', 'Arial Unicode MS']
plt.rcParams['axes.unicode_minus'] = False

class StockAnalyzer:
    """比亚迪股票数据分析器"""
    
    def __init__(self, file_path):
        """初始化分析器并加载数据
        
        Args:
            file_path: Excel文件路径
        """
        self.file_path = file_path
        self.data = None
        self.load_data()
        
    def load_data(self):
        """加载Excel数据并进行预处理"""
        print(f"正在加载数据: {self.file_path}")
        try:
            # 读取Excel文件
            self.data = pd.read_excel(self.file_path)
            
            # 确保日期列格式正确
            if '日期' in self.data.columns:
                self.data['日期'] = pd.to_datetime(self.data['日期'])
                self.data.set_index('日期', inplace=True)
            
            print(f"数据加载完成，共{len(self.data)}条记录")
            print(f"数据列: {list(self.data.columns)}")
            print("前5行数据预览:")
            print(self.data.head())
            
        except Exception as e:
            print(f"数据加载错误: {e}")
    
    def calculate_correlation(self):
        """计算变量之间的相关系数"""
        if self.data is None:
            print("请先加载数据")
            return
        
        try:
            # 选择数值型列计算相关系数
            numeric_cols = self.data.select_dtypes(include=['float64', 'int64']).columns
            corr_matrix = self.data[numeric_cols].corr()
            
            print("相关系数矩阵:")
            print(corr_matrix)
            
            return corr_matrix
        except Exception as e:
            print(f"计算相关系数错误: {e}")
            return None
    
    def plot_correlation_heatmap(self):
        """绘制相关系数热力图"""
        corr_matrix = self.calculate_correlation()
        if corr_matrix is None:
            return
        
        plt.figure(figsize=(12, 10))
        sns.heatmap(corr_matrix, annot=True, cmap='coolwarm', linewidths=0.5, fmt='.2f')
        plt.title('比亚迪股票数据相关系数热力图')
        plt.tight_layout()
        plt.savefig('correlation_heatmap.png', dpi=300)
        print("相关系数热力图已保存为 correlation_heatmap.png")
        plt.close()  # 关闭图表，释放内存
    
    def plot_2023_close_price(self):
        """绘制2023年全年的收盘价时序图"""
        if self.data is None:
            print("请先加载数据")
            return
        
        try:
            # 筛选2023年的数据
            # 由于测试显示所有数据都是2023年的，这里可以直接使用全部数据
            data_2023 = self.data
            
            if data_2023.empty:
                print("未找到数据")
                return
            
            # 使用正确的列名'收盘'
            close_col = '收盘'
            if close_col not in data_2023.columns:
                close_col = '收盘价'  # 备选列名
            
            plt.figure(figsize=(14, 7))
            plt.plot(data_2023.index, data_2023[close_col], 'b-', linewidth=2)
            plt.title('比亚迪2023年收盘价时序图')
            plt.xlabel('日期')
            plt.ylabel('收盘价(元)')
            plt.grid(True, linestyle='--', alpha=0.7)
            plt.tight_layout()
            plt.savefig('2023_close_price.png', dpi=300)
            print("2023年收盘价时序图已保存为 2023_close_price.png")
            plt.close()  # 关闭图表，释放内存
        except Exception as e:
            print(f"绘制时序图错误: {e}")
    
    def plot_k_line_chart(self):
        """绘制2023年4月至6月的K线图"""
        if self.data is None:
            print("请先加载数据")
            return
        
        try:
            # 测试结果显示实际列名为：开盘、最高、最低、收盘、成交量
            # 创建临时数据副本并按照mplfinance要求重命名列
            temp_data = self.data.copy()
            
            # 重命名列为mplfinance所需的英文列名
            column_mapping = {
                '开盘': 'Open',
                '最高': 'High',
                '最低': 'Low',
                '收盘': 'Close',
                '成交量': 'Volume'
            }
            
            # 重命名列
            temp_data.rename(columns=column_mapping, inplace=True)
            print(f"已将列重命名为: {list(temp_data.columns)}")
            
            # 筛选2023年4月至6月的数据
            start_date = '2023-04-01'
            end_date = '2023-06-30'
            data_april_june = temp_data.loc[start_date:end_date]
            
            if data_april_june.empty:
                print(f"未找到{start_date}至{end_date}的数据")
                return
            
            print(f"已筛选{len(data_april_june)}条2023年4-6月的数据")
            
            # 绘制K线图并直接保存，不显示
            mpf.plot(data_april_june, 
                     type='candle', 
                     title='比亚迪2023年4月至6月K线图',
                     ylabel='价格(元)',
                     volume=True,
                     ylabel_lower='成交量',
                     show_nontrading=False,
                     style='yahoo',
                     savefig=dict(fname='k_line_chart.png', dpi=300))
            
            print("K线图已保存为 k_line_chart.png")
            plt.close('all')  # 关闭所有图表，释放内存
            
        except Exception as e:
            print(f"绘制K线图错误: {e}")
    
    def analyze_k_line_patterns(self):
        """分析K线图模式"""
        print("K线图分析报告:")
        print("1. 趋势分析: 观察价格的整体走向，判断是上升趋势、下降趋势还是横盘整理")
        print("2. 支撑位和阻力位: 寻找价格反复测试的关键水平")
        print("3. 成交量分析: 观察成交量与价格变化的关系，判断市场情绪")
        print("4. K线形态识别: 寻找常见的K线组合形态，如锤子线、吞没形态等")
        print("5. 波动性分析: 观察价格波动的幅度和频率")

if __name__ == "__main__":
    # 创建分析器实例
    analyzer = StockAnalyzer('比亚迪后复权历史行情数据.xlsx')
    
    # 执行各项分析任务
    print("\n=== 执行相关系数分析 ===")
    analyzer.plot_correlation_heatmap()
    
    print("\n=== 绘制2023年收盘价时序图 ===")
    analyzer.plot_2023_close_price()
    
    print("\n=== 绘制2023年4月至6月K线图 ===")
    analyzer.plot_k_line_chart()
    
    print("\n=== K线图分析 ===")
    analyzer.analyze_k_line_patterns()
    
    print("\n分析完成！")